<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>AI形成性评价</title>
    <!-- 引入Vue2 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <style>
      /* 主容器样式 */
      .app-container {
        max-width: 900px;
        margin: 0 auto;
        padding: 10px 20px 30px;
      }

      /* 标题区域 */
      .header {
        text-align: center;
        padding-bottom: 8px;
        /* border-bottom: 2px solid #2c3e50; */
      }
      .header h1 {
        margin: 0;
        color: #2c3e50;
        font-size: 22px;
      }

      .borderCon{
        height: 2px;
        margin-bottom: 20px;
        width: 100%;
         /* 背景尺寸为40px×40px（20px红色+20px绿色） */
        background-size: 20px 20px;
        /* 45度倾斜的线性渐变，通过重复实现交替效果 */
        background-image: linear-gradient(45deg, 
          #00cc99 25%,  /* 红色占25%（对应20px） */
          #E5FAF5 25%,  /* 绿色从25%开始 */
          #E5FAF5 50%,  /* 绿色占25%（对应20px） */
          #00cc99 50%,  /* 红色从50%开始 */
          #00cc99 75%,  /* 红色再占25% */
          #E5FAF5 75%   /* 绿色再占25% */
        );
        /* 可选：添加尺寸让效果更明显 */
      }

      /* 聊天内容区域 */
      .chat-container {
        background-color: #f9f9f9;
        border-radius: 10px;
        padding: 20px 25px;
        min-height: 400px;
        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
      }

      /* 消息内容基础样式 - 核心换行控制 */
      .message-content {
        line-height: 1.8;
        color: #333;
        font-size: 15px;
        width: 100%;
        white-space: normal;
        word-wrap: break-word;
      }

      /* 三级标题（###）样式 */
      .level-1 {
        font-size: 18px;
        font-weight: bold;
        color: #2c3e50;
        margin: 15px 0 15px;
        padding-bottom: 5px;
        border-bottom: 1px solid #ddd;
        position: relative;
        padding-left: 30px;
        white-space: normal;
      }
      .level-1::before {
        content: attr(data-index);
        position: absolute;
        left: 0;
        color: #2c3e50;
        font-weight: 600;
      }

      /* 二级列表项（-**）样式 */
      .level-2 {
        font-size: 16px;
        font-weight: bold;
        color: #2c3e50;
        margin: 15px 0 15px;
        padding-bottom: 5px;
        border-bottom: 1px solid #ddd;
        position: relative;
        padding-left: 30px;
        white-space: normal;
      }
      .level-2::before {
        content: attr(data-index);
        position: absolute;
        left: 0;
        color: #2c3e50;
        font-weight: 600;
      }
      /* .level-2 {
        font-size: 16px;
        font-weight: 600;
        color: #34495e;
        margin: 15px 0 10px;
        padding-left: 40px;
        position: relative;
        white-space: normal;
      }
      .level-2::before {
        content: attr(data-index);
        position: absolute;
        left: 15px;
        color: #34495e;
      } */

      /* 普通列表项（-）样式 */
      .list-item {
        margin: 8px 0;
        padding-left: 0;
        text-indent: 40px;
        position: relative;
        white-space: normal;
      }
      .list-item::before {
        content: attr(data-index);
        position: absolute;
        left: -18px;
        color: #2c3e50;
        font-weight: 600;
      }

      /* 详情内容样式 */
      .detail-content {
        margin: 5px 0 15px;
        padding-left: 0;
        color: #555;
        text-align: justify;
        text-indent: 2em;
        white-space: normal;
        word-wrap: break-word;
      }

      /*** 包裹内容加粗样式 **/
      .bold-text {
        font-weight: bold;
        color: #2c3e50;
        display: inline;
        white-space: normal;
        word-break: break-all;
      }

      /* 加载状态 - 颜色修改为#00cc99 */
      .loading-indicator {
        display: inline-block;
        width: 16px;
        height: 16px;
        /* 边框颜色改为#00cc99的浅色透明版 */
        border: 3px solid rgba(0, 204, 153, 0.3);
        border-radius: 50%;
        /* 旋转的边框颜色改为#00cc99 */
        border-top-color: #00cc99;
        animation: spin 1s ease-in-out infinite;
      }

      /* 错误提示 */
      .error-container {
        background-color: #f8d7da;
        color: #721c24;
        padding: 15px;
        border-radius: 5px;
        margin-top: 15px;
        border: 1px solid #f5c6cb;
      }

      @keyframes spin {
        to {
          transform: rotate(360deg);
        }
      }

      .hidden {
        display: none;
      }

      .line-break {
        height: 10px;
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="app-container">
        <div class="header">
          <h1>{{ examName }}</h1>
        </div>
        <div class='borderCon'></div>
        <div class="chat-container">
          <div id="messageContent" class="message-content" v-html="formattedContent"></div>
          <div class="loading-indicator" v-if="isLoading"></div>
          <div class="error-container" v-if="hasError">{{ errorMessage }}</div>
        </div>
      </div>
    </div>

    <script>
      // 不使用export，直接创建Vue实例
      new Vue({
        el: "#app",
        data() {
          return {
            fullMessage: "",
            formattedContent: "",
            isLoading: true,
            hasError: false,
            errorMessage: "",
            examName: "",
            // 配置参数
            AppConfig: {
              API_ENDPOINTS: {
                CONTENT: "https://sa.solacemeta.com/platform-api/app/huoshan/aiContent",
                CHAT_COMPLETION: "https://ark.cn-beijing.volces.com/api/v3/chat/completions",
              },
              AI_MODEL: "doubao-1-5-pro-32k-250115",
              AUTH_TOKEN: "Bearer b3025ba7-2241-4794-b983-5089b0719ea6",
              REQUIRED_PARAMS: ["token", "examinationId"],
            },

            // 层级序号管理
            level1Index: 0,
            level2Index: 0,
            listItemIndex: 0,
            lastLevel: 0,
          }
        },
        mounted() {
          this.init()
        },
        methods: {
          // 初始化应用
          async init() {
            try {
              this.isLoading = true
              this.hasError = false

              // 获取并验证URL参数
              const urlParams = this.parseUrlParams()

              this.validateParams(urlParams)
              this.examName = urlParams.examName
              // 获取内容数据
              const contentData = await this.fetchContentData(urlParams)
              if (!contentData.content) {
                throw new Error("内容数据不完整")
              }

              // 发起聊天请求
              const messages = [
                {
                  role: "user",
                  content: contentData.content,
                },
              ]
              await this.processStream(await this.streamChat(messages))
            } catch (error) {
              this.handleError(error)
            }
          },

          // 解析URL参数
          parseUrlParams() {
            const params = {}
            const queryString = window.location.search.slice(1)

            if (queryString) {
              queryString.split("&").forEach(pair => {
                const [key, value] = pair.split("=")
                if (key) {
                  params[key] = decodeURIComponent(value || "")
                }
              })
            }
            return params
          },

          // 验证参数
          validateParams(params) {
            const missingParams = this.AppConfig.REQUIRED_PARAMS.filter(param => !params[param])

            if (missingParams.length > 0) {
              throw new Error(`缺少必要参数: ${missingParams.join(", ")}`)
            }
          },

          // 处理加粗内容
          formatBoldText(text) {
            return text.replace(/\*\*([\s\S]*?)\*\*/g, (match, content) => {
              const withLineBreaks = content.trim().replace(/\n/g, "<br>")
              return withLineBreaks ? `<span class="bold-text">${withLineBreaks}</span>` : ""
            })
          },

          // 格式化流式内容
          formatStreamContent(text) {
            const lines = text.split("\n")
            let html = ""

            // 重置序号（每次格式化都重新计算序号，避免状态混乱）
            this.level1Index = 0
            this.level2Index = 0
            this.listItemIndex = 0
            this.lastLevel = 0

            lines.forEach(line => {
              const trimmedLine = line.trim()

              // 处理空行
              if (trimmedLine === "") {
                html += '<p class="line-break"></p>'
                return
              }

              // 处理加粗内容
              const formattedLine = this.formatBoldText(line)

              // 处理三级标题（###）
              if (line.startsWith("### ")) {
                this.level1Index++
                this.level2Index = 0
                this.listItemIndex = 0
                this.lastLevel = 1
                const title = formattedLine.replace("### ", "").trim()
                html += `<div class="level-1" data-index="${this.level1Index}.">${title}</div>`
              }
              // 处理二级列表项（-**）
              else if (line.startsWith("-** ")) {
                if (this.lastLevel !== 2) this.level2Index = 0
                this.level2Index++
                this.listItemIndex = 0
                this.lastLevel = 2
                const content = formattedLine.replace("-** ", "").trim()
                html += `<div class="level-2" data-index="${this.level1Index}.${this.level2Index}">${content}</div>`
              }
              // 处理普通列表项（-）
              else if (line.startsWith("- ")) {
                if (this.lastLevel !== 3) this.listItemIndex = 0
                this.listItemIndex++
                this.lastLevel = 3
                const content = formattedLine.replace("- ", "").trim()
                html += `<div class="list-item" data-index="${this.listItemIndex}.">${content}</div>`
              }
              // 处理详情内容
              else if (this.lastLevel > 0) {
                html += `<div class="detail-content">${formattedLine.trim()}</div>`
              }
              // 普通文本
              else {
                html += `<div>${formattedLine.trim()}</div>`
              }
            })

            return html
          },

          // 获取内容数据
          async fetchContentData(params) {
            try {
              const response = await fetch(this.AppConfig.API_ENDPOINTS.CONTENT, {
                method: "POST",
                headers: {
                  "Content-Type": "application/json",
                  token: params.token,
                },
                body: JSON.stringify({
                  examinationId: params.examinationId,
                }),
              })

              return this.handleResponse(response)
            } catch (error) {
              throw new Error(`获取内容失败: ${error.message}`)
            }
          },

          // 发起聊天请求
          async streamChat(messages) {
            try {
              const response = await fetch(this.AppConfig.API_ENDPOINTS.CHAT_COMPLETION, {
                method: "POST",
                headers: {
                  "Content-Type": "application/json",
                  Authorization: this.AppConfig.AUTH_TOKEN,
                },
                body: JSON.stringify({
                  model: this.AppConfig.AI_MODEL,
                  stream: true,
                  messages: messages,
                  temperature: 0.9
                  // thinking:{
                  //   "type": "disabled"
                  // }
                }),
              })

              if (!response.ok) {
                throw new Error(`聊天接口错误: ${response.status}`)
              }

              return response.body.getReader()
            } catch (error) {
              throw new Error(`聊天请求失败: ${error.message}`)
            }
          },

          // 处理API响应
          async handleResponse(response) {
            if (!response.ok) {
              throw new Error(`HTTP错误: ${response.status} ${response.statusText}`)
            }

            const data = await response.json()

            if (!data || typeof data !== "object") {
              throw new Error("接口返回格式不正确")
            }

            return data
          },

          // 处理流式响应
          async processStream(reader) {
            try {
              const decoder = new TextDecoder()

              while (true) {
                const { done, value } = await reader.read()
                if (done) {
                  this.isLoading = false
                  break
                }

                const chunk = decoder.decode(value)
                this.processChunk(chunk)
              }
            } catch (error) {
              this.handleError(error)
            }
          },

          // 处理数据块
          processChunk(chunk) {
            chunk.split("\n").forEach(line => {
              if (line.startsWith("data: ")) {
                try {
                  const data = JSON.parse(line.slice(6))
                  if (data.choices?.[0]?.delta?.content) {
                    this.fullMessage += data.choices[0].delta.content
                    this.formattedContent = this.formatStreamContent(this.fullMessage)
                    this.scrollToBottom()
                  }
                } catch (e) {
                  if (!line.includes("[DONE]")) {
                    console.warn("解析数据块失败:", e)
                  }
                }
              }
            })
          },

          // 滚动到底部
          scrollToBottom() {
            const container = document.getElementById("messageContent")
            if (container) {
              container.scrollTop = container.scrollHeight
            }
          },

          // 处理错误
          handleError(error) {
            this.isLoading = false
            this.hasError = true
            this.errorMessage = error.message
            console.error("应用错误:", error)
          },
        },
      })
    </script>
  </body>
</html>